package com.taldh.netty.io.filedemo;

import com.taldh.netty.common.util.IOUtil;
import com.taldh.netty.common.util.Logger;
import com.taldh.netty.io.NioDemoConfig;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class FileNioCopyDemo {

    public static void main(String[] args) {
        nioCopyResourceFile();
    }

    /**
     * 复制两个资源文件目录下的文件
     */
    public static void nioCopyResourceFile() {
        String sourcePath = NioDemoConfig.FILE_RESOURCE_SRC_PATH;
        String srcPath = IOUtil.getResourcePath(sourcePath);
        Logger.debug("srcPath=" + srcPath);

        String destShortPath = NioDemoConfig.FILE_RESOURCE_DEST_PATH;
        String destdePath = IOUtil.builderResourcePath(destShortPath);
        Logger.debug("destdePath=" + destdePath);

        nioCopyFile(srcPath, destdePath);
    }

    /**
     * 复制文件
     */
    public static void nioCopyFile(String srcPath, String destPath) {
        File srcFile = new File(srcPath);
        File destFile = new File(destPath);

        // 1. 如果目标文件不存在，则新建
        try {
            if (!destFile.exists()) {
                destFile.createNewFile();
            }
            long startTime = System.currentTimeMillis();

            try ( FileInputStream fis = new FileInputStream(srcFile); // 创建一个文件输入流
                  FileOutputStream fos = new FileOutputStream(destFile); //创建一个文件输出流
                  FileChannel inChannel = fis.getChannel();
                  FileChannel outChannel = fos.getChannel()
            ) {
                // 2. 从输入通道读取到buf
                ByteBuffer buf = ByteBuffer.allocate(1024);
                int length = -1;
                while ((length = inChannel.read(buf)) != -1) {
                    // 3. 翻转buf,变成成读模式
                    buf.flip();

                    // 4. 将buf写入到输出的通道
                    int outLength = 0;
                    while ((outLength = outChannel.write(buf)) != 0) {
                        System.out.println("写入的字节数：" + outLength);
                    }
                    // 5. 清除buf,变成写入模式
                    buf.clear();
                }
                // 6. 强制刷新磁盘
                outChannel.force(true);

            } catch (IOException ioException) {
                ioException.printStackTrace();
            }

            long endTime = System.currentTimeMillis();
            Logger.debug("base 复制毫秒数：" + (endTime - startTime));

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 更加高效的文件传输通道：transferFrom
     */
    public void nioFastCopyFile(String srcPath, String destPath) {
        File srcFile = new File(srcPath);
        File destFile = new File(destPath);

        // 1. 如果目标文件不存在，则新建
        try {
            if (!destFile.exists()) {
                destFile.createNewFile();
            }
            long startTime = System.currentTimeMillis();

            try ( FileInputStream fis = new FileInputStream(srcFile); // 创建一个文件输入流
                  FileOutputStream fos = new FileOutputStream(destFile); //创建一个文件输出流
                  FileChannel inChannel = fis.getChannel();
                  FileChannel outChannel = fos.getChannel()
            ) {
                long size = inChannel.size();
                long pos = 0;
                long count = 0;
                while (pos < size) {
                    //每次复制最多1024个字节，没有剩余的
                    count = size - pos > 1024 ? 1024 : size - pos;
                    //复制内存，偏移量pos + count 长度
                    pos += outChannel.transferFrom(inChannel, pos, count);
                }
                //强制刷新到磁盘
                outChannel.force(true);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
